﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ServiceModel;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
using System.Diagnostics;

namespace WcfInspectorLib
{
    /// <summary>
    ///  服务端消息拦截器
    /// </summary>
    public class ServerMessageInspector : IDispatchMessageInspector, IEndpointBehavior, IDisposable
    {
        /// <summary>
        /// 收到客户端请求之后
        /// </summary>
        internal event EventHandler<AfterReceiveRequestEventArgs> AfterReceiveRequest;
        /// <summary>
        /// 回复客户端之前
        /// </summary>
        internal event EventHandler<BeforeSendReplyEventArgs> BeforeSendReply;

        public List<BaseMessageListener> MessageListeners { get; private set; }

        public ServerMessageInspector AddListener<T>() where T : BaseMessageListener, new()
        {
            if (MessageListeners == null) MessageListeners = new List<BaseMessageListener>();
            T listener = new T() { Inspector = this };
            MessageListeners.Add(listener);
            return this;
        }

        public ServerMessageInspector AddListener<T>(T listener) where T: BaseMessageListener
        {
            if (MessageListeners == null) MessageListeners = new List<BaseMessageListener>();
            if (!MessageListeners.Contains(listener))
            {
                listener.Inspector = this;
                MessageListeners.Add(listener);
            }
            return this;
        }

        public void Dispose()
        {
            if (MessageListeners == null) return;
            foreach (var listener in MessageListeners)
            {
                AfterReceiveRequest -= listener.AfterReceiveRequest;
                BeforeSendReply -= listener.BeforeSendReply;
            }
            MessageListeners.Clear();
        }

        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {

        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {

        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this);
        }

        public void Validate(ServiceEndpoint endpoint)
        {

        }

        object IDispatchMessageInspector.AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        {
            if (AfterReceiveRequest != null)
            {
                var args = new AfterReceiveRequestEventArgs(request, channel, instanceContext);
                AfterReceiveRequest(this, args);
            }
            return null;
        }

        void IDispatchMessageInspector.BeforeSendReply(ref Message reply, object correlationState)
        {
            if (BeforeSendReply == null) return;
            BeforeSendReply(this, new BeforeSendReplyEventArgs(reply, correlationState));
        }
    }
}
